/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			pgitem.h
  \date			Aug 2012
  \author		TNick

  \brief		Contains the definition for PgItem class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef __PGITEM_INC__
#define __PGITEM_INC__
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<cpg/cpg.h>
#include	<memtrack.h>
#include	<2D/abox2d.h>
#include	<cpg/logic/characteristics/pgcolor.h>
#include	<cpg/logic/characteristics/pglnpattern.h>
#include	<cpg/logic/characteristics/pglnpattscale.h>
#include	<cpg/logic/characteristics/pglnwidth.h>
#include	<cpg/properties/iprop.h>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

class	QDomElement;

namespace	cpg		{

class	CpgDoc;
class	PgSpace;
class	PgLayer;
class	PgBlockRef;
class	PgBlockDfn;


/**
*	@brief	The basic graphical item in a document
*
*	The items are hosted inside layers (that may be global or part of a space).
*/
class CPGSHARED_EXPORT PgItem		: public IProp		{
	BBM_TRACK( PgItem );

	//
	//
	//
	//
	/*  DEFINITIONS    ----------------------------------------------------- */

	/*  DEFINITIONS    ===================================================== */
	//
	//
	//
	//
	/*  DATA    ------------------------------------------------------------ */

private:

	/**
	*	@brief	parent layer
	*/
	PgLayer *					layer_;


	/**
	*	@brief	parent block
	*/
	PgBlockRef *				block_;


	/**
	*	@brief	parent space
	*/
	PgSpace *					space_;


	/**
	*	@brief	weight of the line
	*/
	PgLnWeight::Id				ln_weight_;


	/**
	*	@brief	scale of the pattern
	*/
	PgLnPattScale::Id			ln_scale_;


	/**
	*	@brief	the color to use
	*/
	PgColor::Id					color_;


	/**
	*	@brief	the line pattern to use
	*/
	PgLnPattern::Id				ln_patt_;


	/*  DATA    ============================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ------------------------------------------------------- */

public:


	/**
	*	@brief	constructor;
	*	@param	ly		the parent layer
	*	@param	spc		the parent space
	*
	*	The constructor does not insert the item into parent layer. It only
	*	stores provided data and initialises the rest of the members to default.
	*/
	PgItem				( PgLayer * ly, PgSpace * spc );


	/**
	*	@brief	destructor;
	*/
	virtual				~PgItem				( void );




	/* ******************************************************************* */
	/** @name 	Report the status of internal properties                   */
	/* ******************************************************************* */
	///@{


public:


	/**
	*	@brief	the layer this item is part of
	*/
	inline PgLayer *		layer			( void ) const
	{ return layer_; }


	/**
	*	@brief	the block instance this item is part of
	*/
	inline PgBlockRef *		block			( void ) const
	{ return block_; }


	/**
	*	@brief	the space this item is part of
	*/
	inline PgSpace *		space			( void ) const
	{ return space_; }


	/**
	*	@brief	the document this item is part of
	*/
	CpgDoc *					document		( void ) const;


	/**
	*	@brief	the color as an index
	*/
	inline PgColor::Id			color			( void ) const
	{ return color_; }


	/**
	*	@brief	the line pattern as an index
	*/
	inline PgLnPattern::Id		lnPattern		( void ) const
	{ return ln_patt_; }


	/**
	*	@brief	the weight of lines
	*/
	inline PgLnWeight::Id		lineWeight		( void ) const
	{ return ln_weight_; }


	/**
	*	@brief	the scale for line pattern
	*/
	inline PgLnPattScale::Id	linePattScl		( void ) const
	{ return ln_scale_; }


	///@}
	/* ******************************************************************* */




	/* ******************************************************************* */
	/** @name 	Methods that the inheritant must implement                 */
	/* ******************************************************************* */
	///@{


public:


	/**
	*	@brief	Create a deep copy of the object
	*/
	virtual PgItem *	clone						( void ) = 0;


	/**
	*	@brief	Scales the item given the arguments
	*	@param	base		the point around which we're scalling
	*	@param	factor		the scale ammount
	*/
	virtual void		scale						(
			P2D &				base,
			qreal				factor
			) = 0;


	/**
	*	@brief	Scales the item given the arguments
	*	@param	base		the point around which we're rotating
	*	@param	angle		the rotation
	*/
	virtual void		rotate						(
			P2D &				base,
			qreal				angle
			) = 0;


	/**
	*	@brief	Get a string representation of this item
	*/
	virtual QString		stringify					( void ) = 0;


	/**
	*	@brief	move the item, relative to its current position
	*	@param	dx		displacement on true x axis
	*	@param	dy		displacement on true y axis
	*
	*	This only stores newe position; has no effect outside the instance.
	*/
	virtual void		translate					(
			qreal				dx,
			qreal				dy
			) = 0;


	/**
	*	@brief	bounding box for the item
	*	@param	rect		the box is returned in this parameter
	*/
	virtual void		boundingBox					(
			ABOX2D &			rect
			) = 0;


	/**
	*	@brief	tell if this item is visible in given box
	*	@param	rect		the box to test
	*/
	virtual bool		visibleIn					(
			const ABOX2D &		rect
			) = 0;


	/**
	*	@brief	save the item as an XML element
	*	@param	dest		where to save
	*
	*	The implementation should make use of the genericToXml() method
	*/
	virtual bool		toXML					(
			QDomElement &		dest
			) const = 0;


	///@}
	/* ******************************************************************* */



	/* ******************************************************************* */
	/** @name 	Methods that the inheritant may implement                  */
	/* ******************************************************************* */
	///@{


public:


	/**
	*	@brief	tell if this is a block or not
	*/
	virtual bool		isBlock					( void )
	{ return false; }


	///@}
	/* ******************************************************************* */



	/* ******************************************************************* */
	/** @name 	Methods for directly changing internal properties          */
	/* ******************************************************************* */
	///@{

protected:


	/**
	*	@brief	change display color; only changes internal state
	*/
	void				forcePrimaryColor			( PgColor::Id new_value )
	{ color_ = new_value; }


	/**
	*	@brief	change line weight; only changes internal state
	*/
	void				forceLineWeight				( PgLnWeight::Id new_value )
	{ ln_weight_ = new_value; }


	/**
	*	@brief	change line pattern ; only changes internal state
	*/
	void				forceLinePatt				( PgLnPattern::Id new_value )
	{ ln_patt_ = new_value; }


	/**
	*	@brief	change line pattern scale; only changes internal state
	*/
	void				forceLinePattScl			( PgLnPattScale::Id new_value )
	{ ln_scale_ = new_value; }


	/**
	*	@brief	change the layer; only changes internal state
	*/
	void				forceLayer					( PgLayer * new_val )
	{ layer_ = new_val; }


	/**
	*	@brief	change the parent block; only changes internal state
	*/
	void				forceBlock					( PgBlockRef * new_val )
	{ block_ = new_val; }


	///@}
	/* ******************************************************************* */



	/* ******************************************************************* */
	/** @name 	Various other methods                                      */
	/* ******************************************************************* */
	///@{


public:

	/**
	*	@brief	insert the item in associated layer
	*
	*	This is intended for redo action, when the state is saved inside
	*	the item and all that's left to be done is to insert the item in the
	*	list of items owned by the layer.
	*
	*	@return false if there is no associated layer or the item is already
	*	insered
	*/
	bool					insert			( void );


	/**
	*	@brief	extracts the item from associated layer
	*
	*	This is intended for undo action, when the state is saved inside
	*	the item and all that's left to be done is to extract the item from the
	*	list of items owned by the layer.
	*
	*	@return false if there is no associated layer or the item is already
	*	removed
	*/
	bool					extract			( void );


	/**
	*	@brief	saves generic properties (color, linetype,...) directly
	*	inside provided element
	*/
	void					genericToXml	( QDomElement & dest );


	/**
	*	@brief	change a common property using an index
	*	@param	idx		the property to change as an index
	*	@param	value	new value for this property
	*/
	bool					setCommonProp	(
			PropIndex				idx,
			int						value
			);


	///@}
	/* ******************************************************************* */



	/*  FUNCTIONS    ======================================================= */
	//
	//
	//
	//

};	/*	class PgItem	*/

/*  CLASS    =============================================================== */
//
//
//
//

}	//	namespace	cpg

#endif // __PGITEM_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
